package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

type singleton struct{}

func (s *singleton) Greet() {
	fmt.Println("hello")
}

var (
	instance    *singleton
	initialized uint32
	mu          sync.Mutex
)

func Instance() *singleton {
	if atomic.LoadUint32(&initialized) == 1 {
		return instance
	}

	mu.Lock()
	defer mu.Unlock()

	if instance == nil {
		defer atomic.StoreUint32(&initialized, 1)
		fmt.Println("initialize singleton")
		instance = &singleton{}
	}
	return instance
}

func main() {
	Instance().Greet()
	Instance().Greet()
	Instance().Greet()
}
